using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using Microsoft.VisualStudio.Shell;
using AntEater.ComponentModel;
using AntEater.Runtime;
using AntEater.Runtime.UI;


namespace AntEater.Integration.OptionPages
{
    /// <summary>
    /// Provides the option page for the external build properties.
    /// </summary>
    [Guid(Guids.ExternalBuildPropertiesOptionPageId)]
    [CLSCompliant(false)]
    public class ExternalBuildPropertiesOptionPage : DialogPage
    {
        IOptionsPresenter _presenter;
        /// <summary>
        /// Initializes a new instance of the <see cref="ExternalBuildPropertiesOptionPage"/> class.
        /// </summary>
        public ExternalBuildPropertiesOptionPage()
            : base() {
            _externalBuildProperties = new ExternalBuildPropertyCollection();

            IAntEaterRuntime runtime = AntEaterRuntime.Instance;
            _presenter = runtime.Presenters.GetService(typeof(IOptionsPresenter)) as IOptionsPresenter;
        }

        private ExternalBuildPropertyCollection _externalBuildProperties;

        /// <summary>
        /// Gets the external build properties.
        /// </summary>
        /// <value>The external build properties.</value>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ExternalBuildPropertyCollection ExternalBuildProperties {
            get { return _externalBuildProperties; }
        }

        /// <summary>
        /// Gets or sets the external build properties as string.
        /// </summary>
        /// <value>The external build properties as string.</value>
        [Category(Strings.ExternalBuildPropertiesCategory)]
        [DisplayName(Strings.ExternalBuildPropertiesName)]
        [Description(Strings.ExternalBuildPropertiesDescription)]
        public string ExternalBuildPropertiesString {
            get {
                // Serialize external build properties in to string
                StringBuilder xml = new StringBuilder();

                using (StringWriter writer = new StringWriter(xml, CultureInfo.InvariantCulture )) {
                    XmlSerializer serializer = new XmlSerializer(typeof(ExternalBuildPropertyCollection));
                    serializer.Serialize(writer, _externalBuildProperties);
                }

                return xml.ToString();
            }
            set {
                // Deserialize external build properties out of a string
                using (StringReader reader = new StringReader(value)) {
                    XmlSerializer serializer = new XmlSerializer(typeof(ExternalBuildPropertyCollection));

                    _externalBuildProperties.Clear();
                    _externalBuildProperties.AddRange((ExternalBuildPropertyCollection)serializer.Deserialize(reader));
                }
            }
        }

        /// <summary>
        /// Gets the window.
        /// </summary>
        /// <value>The window.</value>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        protected override IWin32Window Window {
            get {
                // get the control to display from the presenter
                Control control = _presenter.View.Surface;
                control.Location = new Point(0, 0);
                return control;
            }
        }

        /// <summary>
        /// Loads the settings from storage.
        /// </summary>
        public override void LoadSettingsFromStorage() {
            base.LoadSettingsFromStorage();

            // set all externel build properties on the presenter
            _presenter.ExternalBuildProperties.Clear();
            _presenter.ExternalBuildProperties.AddRange(_externalBuildProperties);
            _presenter.Refresh();
        }

        /// <summary>
        /// Raises the <see cref="E:Apply"/> event.
        /// </summary>
        /// <param name="e">The <see cref="Microsoft.VisualStudio.Shell.DialogPage.PageApplyEventArgs"/> instance containing the event data.</param>
        protected override void OnApply(PageApplyEventArgs e) {

            if (e.ApplyBehavior == ApplyKind.Apply) {
                // set all external build properties from the presenter
                _externalBuildProperties.Clear();
                _externalBuildProperties.AddRange(_presenter.ExternalBuildProperties);

                // Apply options on the runtime instance
                Options options = AntEaterRuntime.Instance.Options;
                options.ExternalBuildProperties.Clear();
                options.ExternalBuildProperties.AddRange(_externalBuildProperties);
            }

            base.OnApply(e);
        }

        /// <summary>
        /// Raises the <see cref="E:Closed"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected override void OnClosed(EventArgs e) {

            // set all externel build properties on the presenter
            _presenter.ExternalBuildProperties.Clear();
            _presenter.ExternalBuildProperties.AddRange(_externalBuildProperties);
            _presenter.Refresh();
            base.OnClosed(e);
        }
    }
}
